package com.vimhe.easyimport.validate;

import com.vimhe.easyimport.config.bean.CellConfig;
import com.vimhe.easyimport.util.ValidateUtils;

import java.math.BigDecimal;
import java.sql.Date;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 默认数据校验器
 *
 * @author Vimhe
 */
public class DefaultDataValidator implements DataValidator {

    @Override
    public List<ErrorMessage> validate(String fileName, int sheetIndex, int rowIndex, String cellIndex, CellConfig cellConfig, Object cellValue) {
        Boolean nullable = cellConfig.getNullable();
        Integer minLength = cellConfig.getMinLength();
        Integer length = cellConfig.getLength();
        Integer maxLength = cellConfig.getMaxLength();
        Integer min = cellConfig.getMin();
        Integer max = cellConfig.getMax();
        String regex = cellConfig.getRegex();

        List<ErrorMessage> errorMessages = new ArrayList<>(16);

        if (ValidateUtils.isEmpty(cellValue)) {
            // 没有设置nullable则默认nullable为true
            if (ValidateUtils.isEmpty(nullable) || nullable) {
                return errorMessages;
            } else {
                ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                errorMessage.setErrorMessage("该项不能为空");
                errorMessages.add(errorMessage);
                return errorMessages;
            }
        }

        String val = String.valueOf(cellValue);
        switch (cellConfig.getType()) {
            case "java.lang.String":
                if (Objects.equals("null", val)) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("该项不能为空");
                    errorMessages.add(errorMessage);
                }
                if (minLength != null && minLength > val.length()) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("字段长度小于规定范围：" + minLength);
                    errorMessages.add(errorMessage);
                }
                if (length != null && length != val.length()) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("字段长度不等于规定值：" + length);
                    errorMessages.add(errorMessage);
                }
                if (maxLength != null && maxLength < val.length()) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("字段长度超过规定范围：" + maxLength);
                    errorMessages.add(errorMessage);
                }
                break;
            case "java.lang.Integer":
                Integer aInteger;
                try {
                    aInteger = Integer.valueOf(val);
                    if (min != null && min > aInteger) {
                        ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                        errorMessage.setErrorMessage("字段值小于规定范围：" + val);
                        errorMessages.add(errorMessage);
                    }
                    if (max != null && max < aInteger) {
                        ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                        errorMessage.setErrorMessage("字段值大于规定范围：" + val);
                        errorMessages.add(errorMessage);
                    }
                } catch (NumberFormatException e) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("字段值不是规定的类型：整数");
                    errorMessages.add(errorMessage);
                }
                break;
            case "java.lang.Long":
                Long aLong;
                try {
                    aLong = Long.valueOf(val);
                    if (min != null && min > aLong) {
                        ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                        errorMessage.setErrorMessage("字段值小于规定范围：" + val);
                        errorMessages.add(errorMessage);
                    }
                    if (max != null && max < aLong) {
                        ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                        errorMessage.setErrorMessage("字段值大于规定范围：" + val);
                        errorMessages.add(errorMessage);
                    }
                } catch (NumberFormatException e) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("字段值不是规定的类型：整数");
                    errorMessages.add(errorMessage);
                }
                break;
            case "java.lang.Float":
                Float aFloat;
                try {
                    aFloat = Float.valueOf(val);
                    if (min != null && min > aFloat) {
                        ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                        errorMessage.setErrorMessage("字段值小于规定范围：" + val);
                        errorMessages.add(errorMessage);
                    }
                    if (max != null && max < aFloat) {
                        ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                        errorMessage.setErrorMessage("字段值大于规定范围：" + val);
                        errorMessages.add(errorMessage);
                    }
                } catch (NumberFormatException e) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("字段值不是规定的类型：任意数字");
                    errorMessages.add(errorMessage);
                }
                break;
            case "java.lang.Double":
                Double aDouble;
                try {
                    aDouble = Double.parseDouble(val);
                    if (min != null && min > aDouble) {
                        ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                        errorMessage.setErrorMessage("字段值小于规定范围：" + val);
                        errorMessages.add(errorMessage);
                    }
                    if (max != null && max < aDouble) {
                        ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                        errorMessage.setErrorMessage("字段值大于规定范围：" + val);
                        errorMessages.add(errorMessage);
                    }
                } catch (NumberFormatException e) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("字段值不是规定的类型：任意数字");
                    errorMessages.add(errorMessage);
                }
                break;
            case "java.math.BigDecimal":
                BigDecimal aBigDecimal;
                try {
                    aBigDecimal = BigDecimal.valueOf(Double.parseDouble(val));
                    if (min != null && min > aBigDecimal.intValue()) {
                        ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                        errorMessage.setErrorMessage("字段值小于规定范围：" + val);
                        errorMessages.add(errorMessage);
                    }
                    if (max != null && max < aBigDecimal.intValue()) {
                        ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                        errorMessage.setErrorMessage("字段值大于规定范围：" + val);
                        errorMessages.add(errorMessage);
                    }
                } catch (NumberFormatException e) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("字段值不是规定的类型：任意数字");
                    errorMessages.add(errorMessage);
                }
                break;
            case "java.lang.Boolean":
                Boolean aBoolean = Boolean.TRUE.toString().equalsIgnoreCase(val)
                        || Boolean.FALSE.toString().equalsIgnoreCase(val);
                if (!aBoolean) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("字段值不是有效的布尔类型");
                    errorMessages.add(errorMessage);
                }
                break;
            case "java.lang.Byte":
                try {
                    Byte.valueOf(val);
                } catch (NumberFormatException e) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("字段值不是规定的类型：字节码");
                    errorMessages.add(errorMessage);
                }
                break;
            case "java.util.Date":
                try {
                    DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
                    dateFormat.parse(val);
                } catch (ParseException e) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("无效的日期");
                    errorMessages.add(errorMessage);
                }
                break;
            case "java.sql.Date":
                try {
                    Date.valueOf(val);
                } catch (IllegalArgumentException e) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("无效的日期");
                    errorMessages.add(errorMessage);
                }
                break;
            case "java.sql.Timestamp":
                try {
                    new Timestamp(Date.valueOf(val).getTime());
                } catch (IllegalArgumentException e) {
                    ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                    errorMessage.setErrorMessage("无效的时间戳");
                    errorMessages.add(errorMessage);
                }
                break;
            default:
                break;
        }

        if (ValidateUtils.isNotEmpty(regex)) {
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(val);
            if (!m.matches()) {
                ErrorMessage errorMessage = generalErrorMessage(fileName, sheetIndex, rowIndex, cellIndex, cellConfig, cellValue);
                errorMessage.setErrorMessage("不符合特定规则：" + regex);
                errorMessages.add(errorMessage);
            }
        }

        return errorMessages;
    }

    /**
     * 构造错误消息对象
     *
     * @param fileName   文件标识
     * @param sheetIndex 工作表索引
     * @param rowIndex   行索引
     * @param cellIndex  单元格索引
     * @param cellConfig 单元格配置对象
     * @param cellValue  要验证的数据
     * @return 错误消息对象
     */
    private ErrorMessage generalErrorMessage(String fileName, int sheetIndex, int rowIndex, String cellIndex, CellConfig cellConfig, Object cellValue) {
        return new ErrorMessage()
                .setFileName(fileName)
                .setSheetIndex(sheetIndex)
                .setRowIndex(rowIndex)
                .setCellIndex(cellIndex)
                .setCellValue((String) cellValue);
    }

}
